/*
 * STC_Download.cpp
 *
 *  Created on: 2025年4月22日
 *      Author: Li
 */
#include <string.h>
#include "uart/CommDef.h"
#include "STC_Download.h"

// 加 2 操作是为了让 Keil 编译器
// 自动实现四舍五入运算

// 变量定义
BOOL f1ms;          // 1ms 标志位
BOOL UartBusy;      // 串口发送忙标志位
BOOL UartReceived;  // 串口数据接收完成标志位
BYTE UartRecvStep;  // 串口数据接收控制
BYTE TimeOut;       // 串口通讯超时计数器
BYTE TxBuffer[256]; // 串口数据发送缓冲区
BYTE RxBuffer[256]; // 串口数据接收缓冲区
BYTE DEMO[256];     // 演示代码数据

BYTE my_TxBuffer[256];  // 串口数据发送缓冲区
BYTE my_TxBuffer_count; // 串口数据发送缓冲区计数器

// 主函数入口
void main0(void)
{
   Initial(); // 初始化
   if (Download(DEMO, 256))
   {
      // 下载成功
   }
   else
   {
      // 下载失败
   }
}

// 1ms 定时器中断服务程序
void tm0(void)
{
   static BYTE Counter100;

   f1ms = TRUE;
   if (Counter100-- == 0)
   {
      Counter100 = 100;
      if (TimeOut)
         TimeOut--;
   }
}

void uart(void)
{
   static WORD RecvSum;
   static BYTE RecvIndex;
   static BYTE RecvCount;
   BYTE dat;
   if (0)
   {
      dat = 0xFF;
      switch (UartRecvStep)
      {
      case 1:
         if (dat != 0xb9)
            goto L_CheckFirst;
         UartRecvStep++;
         break;
      case 2:
         if (dat != 0x68)
            goto L_CheckFirst;
         UartRecvStep++;
         break;
      case 3:
         if (dat != 0x00)
            goto L_CheckFirst;
         UartRecvStep++;
         break;
      case 4:
         RecvSum = 0x68 + dat;
         RecvCount = dat - 6;
         RecvIndex = 0;
         UartRecvStep++;
         break;
      case 5:
         RecvSum += dat;
         RxBuffer[RecvIndex++] = dat;
         if (RecvIndex == RecvCount)
            UartRecvStep++;
         break;
      case 6:
         if (dat != HI_BYTE(RecvSum))
            goto L_CheckFirst;
         UartRecvStep++;
         break;
      case 7:
         if (dat != LO_BYTE(RecvSum))
            goto L_CheckFirst;
         UartRecvStep++;
         break;
      case 8:
         if (dat != 0x16)
            goto L_CheckFirst;
         UartReceived = TRUE;
         UartRecvStep++;
         break;
      L_CheckFirst:
      case 0:
      default:
         CommInit();
         UartRecvStep = (dat == 0x46 ? 1 : 0);
         break;
      }
   }
}

void Initial(void)
{
   UartBusy = FALSE;

   // SCON = 0xd0; // 串口数据模式必须为 8 位数据+1 位偶检验
   // AUXR = 0xc0;
   // TMOD = 0x00;
   // TH0 = HI_BYTE(T1MS);
   // TL0 = LO_BYTE(T1MS);
   // TR0 = 1;
   // TH1 = HI_BYTE(BR(MINBAUD));
   // TL1 = LO_BYTE(BR(MINBAUD));
   // TR1 = 1;
   // ET0 = 1;
   // ES = 1;
   // EA = 1;
}

// Xms 延时程序
void DelayXms(WORD x)
{
   // do
   // {
   //    f1ms = FALSE;
   //    while (!f1ms)
   //       ;
   // } while (x--);
}

// 串口数据发送程序
BYTE UartSend(BYTE dat)
{
   my_TxBuffer[my_TxBuffer_count++] = dat;
   return dat;
}

// 串口通讯初始化
void CommInit(void)
{
   UartRecvStep = 0;
   TimeOut = 20;
   UartReceived = FALSE;
}

// 发送串口通讯数据包
void CommSend(BYTE size)
{
   WORD sum;
   BYTE i;

   UartSend(0x46);
   UartSend(0xb9);
   UartSend(0x6a);
   UartSend(0x00);
   sum = size + 6 + 0x6a;
   UartSend(size + 6);
   for (i = 0; i < size; i++)
   {
      sum += UartSend(TxBuffer[i]);
   }
   UartSend(HI_BYTE(sum));
   UartSend(LO_BYTE(sum));
   UartSend(0x16);
   send_UART(my_TxBuffer, my_TxBuffer_count);
   my_TxBuffer_count = 0;
}

// 对 STC15H 系列的芯片进行 ISP 下载程序
BOOL Download(BYTE *pdat, long size)
{
   BYTE arg;
   BYTE offset;
   BYTE cnt;
   WORD addr;

   // 握手
   // CommInit();
   // while (1)
   // {
   //    if (UartRecvStep == 0)
   //    {
   //       UartSend(0x7f);
   //       DelayXms(10);
   //    }
   //    if (UartReceived)
   //    {
   //       arg = RxBuffer[4];
   //       if (RxBuffer[0] == 0x50)
   //          break;
   //       return FALSE;
   //    }
   // }

   // 设置参数(设置从芯片使用最高的波特率以及等待时间等参数)
   TxBuffer[0] = 0x01;
   TxBuffer[1] = arg; // arg
   TxBuffer[2] = 0x40;
   TxBuffer[3] = HI_BYTE(RL(MAXBAUD));
   TxBuffer[4] = LO_BYTE(RL(MAXBAUD));
   TxBuffer[5] = 0x00;
   TxBuffer[6] = 0x00;
   TxBuffer[7] = 0x97;
   CommSend(8);
   return FALSE;
   while (1)
   {
      if (TimeOut == 0)
         return FALSE;
      if (UartReceived)
      {
         if (RxBuffer[0] == 0x01)
            break;
         return FALSE;
      }
   }

   // 准备
   //   TH1 = HI_BYTE(BR(MAXBAUD));
   //   TL1 = LO_BYTE(BR(MAXBAUD));
   DelayXms(10);
   TxBuffer[0] = 0x05;
   TxBuffer[1] = 0x00;
   TxBuffer[2] = 0x00;
   TxBuffer[3] = 0x5a;
   TxBuffer[4] = 0xa5;
   CommSend(5);
   while (1)
   {
      if (TimeOut == 0)
         return FALSE;
      if (UartReceived)
      {
         if (RxBuffer[0] == 0x05)
            break;
         return FALSE;
      }
   }

   // 擦除
   DelayXms(10);
   TxBuffer[0] = 0x03;
   TxBuffer[1] = 0x00;
   TxBuffer[2] = 0x00;
   TxBuffer[3] = 0x5a;
   TxBuffer[4] = 0xa5;
   CommSend(5);
   TimeOut = 100;
   while (1)
   {
      if (TimeOut == 0)
         return FALSE;
      if (UartReceived)
      {
         if (RxBuffer[0] == 0x03)
            break;
         return FALSE;
      }
   }
   // 写用户代码
   DelayXms(10);
   addr = 0;
   TxBuffer[0] = 0x22;
   TxBuffer[3] = 0x5a;
   TxBuffer[4] = 0xa5;
   offset = 5;
   while (addr < size)
   {
      TxBuffer[1] = HI_BYTE(addr);
      TxBuffer[2] = LO_BYTE(addr);
      cnt = 0;
      while (addr < size)
      {
         TxBuffer[cnt + offset] = pdat[addr];
         addr++;
         cnt++;
         if (cnt >= 128)
            break;
      }
      CommSend(cnt + offset);
      while (1)
      {
         if (TimeOut == 0)
            return FALSE;
         if (UartReceived)
         {
            if ((RxBuffer[0] == 0x02) && (RxBuffer[1] == 'T'))
               break;
            return FALSE;
         }
      }
      TxBuffer[0] = 0x02;
   }
   ////写硬件选项
   ////如果不需要修改硬件选项,此步骤可直接跳过,此时所有的硬件选项
   ////都维持不变,MCU 的频率为上一次所调节频率
   ////若写硬件选项,MCU 的内部 IRC 频率将被固定写为 24M, ,其他选项恢复为出厂设置
   ////建议:第一次使用 STC-ISP 下载软件将从芯片的硬件选项设置好
   ////以后再使用主芯片对从芯片下载程序时不写硬件选项
   // DelayXms(10);
   // for (cnt=0; cnt<128; cnt++)
   //{
   //  TxBuffer[cnt] = 0xff;
   // }
   // TxBuffer[0] = 0x04;
   // TxBuffer[1] = 0x00;
   // TxBuffer[2] = 0x00;
   // TxBuffer[3] = 0x5a;
   // TxBuffer[4] = 0xa5;
   // TxBuffer[33] = arg;
   // TxBuffer[34] = 0x00;
   // TxBuffer[35] = 0x01;
   // TxBuffer[41] = 0xbf;
   // TxBuffer[42] = 0xbd; //P5.4 为 IO 口
   ////TxBuffer[42] = 0xad; //P5.4 为复位脚
   // TxBuffer[43] = 0xf7;
   // TxBuffer[44] = 0xff;
   // CommSend(45);
   // while (1)
   //{
   //  if (TimeOut == 0) return FALSE;
   //  if (UartReceived)
   //  {
   //  if ((RxBuffer[0] == 0x04) && (RxBuffer[1] == 'T')) break;
   //  return FALSE;
   //  }
   // 下载完成
   return TRUE;
};
